//Protocol.hpp
#pragma once
#include <jsoncpp/json/json.h>
#include <iostream>
#include <unistd.h>
#include <string>
#include <vector>
#include "Util.hpp"
using namespace std;
#define SEP " "
#define SEP_LEN strlen(SEP)
#define HEADER_SEP "\t\n"
#define HEADER_SEP_LEN strlen(HEADER_SEP)
// #define MYSELF 1

// 添加报头
// 7\t\n10 + 20\t\n->模拟应用层协议
// 7\t\n10 + 20\t\n->运算符和操作符之间有SEP
string AddHeader(const string &payload) // payload是有效载荷
{
    cout << "添加报头前:\n" << payload << endl;
    cout<<"------------------------------------"<<endl;

    string packaging; // packaging是封装
    // 添加报头
    packaging += to_string(payload.size());
    packaging += HEADER_SEP;
    packaging += payload;
    packaging += HEADER_SEP;

    cout << "添加报头后:\n" << packaging << endl;
    cout<<"------------------------------------"<<endl;

    return packaging;
}

// 去报头
// 7\t\n10 + 20\t\n
string DelHeader(const string packaging, int len) // len表示的是有效载荷大小，即7\t\n10 + 20\t\n中的7
{
    cout << "去报头前:\n" << packaging<< endl;
    cout<<"------------------------------------"<<endl;

    string payload = packaging.substr(packaging.size() - HEADER_SEP_LEN - len, len); // 还是以前面的举例，截取10 + 20

    cout << "去报头后:\n" << payload<< endl;
    cout<<"------------------------------------"<<endl;


    return payload;
};

// 读取
// packaging是读取出来的是对方发出的数据（不一定完整）
// out是读取到的完整封装报文
int Parse(string &packaging, string &out)
{
    // char buff[1024] = {0};
    // // 将读取到的数据临时放入buff中
    // int n = recv(sock, buff, sizeof(buff)-1, 0);
    // if (n == 0)
    // {
    //     // 服务器把对应的写关了
    //     return 0;
    // }
    // else if (n < 0)
    // {
    //     return -1;
    // }
    // // 以字符串形式，因此要添加'\0'
    // buff[n] = 0;
    // // 放入packaging，传出去，保证后续报文的完整性
    // // 必须是+=,向剩余报文中继续增加
    // packaging += buff;
    
    // cout << "ReadPackage前:\n" << packaging<< endl;
    // cout<<"------------------------------------"<<endl;

    // 找到报头，即7\t\n10 + 20\t\n中的7
    auto pos = packaging.find(HEADER_SEP);
    if (pos == string::npos)
    {
        return -1;
    }

    // 找到后，进行处理，拿出来
    string string_payloadlen = packaging.substr(0, pos);

    cout << "payload len:" << string_payloadlen << endl;
    cout<<"------------------------------------"<<endl;

    // 转换成整型
    int payloadlen = stoi(string_payloadlen);

    // 计算出报文应有的整体大小
    int targetlen = payloadlen + 2 * HEADER_SEP_LEN + string_payloadlen.size();

    // 读取到的报文整体小于报文应有的整体大小就需要继续读取，由调用者判断
    if (targetlen > packaging.size())
    {
        return -1;
    }

    // 将完整报文分割出来传出去
    out = packaging.substr(0, targetlen);

    // cout << "ReadPackage后:\n" << out<< endl;
    // cout<<"------------------------------------"<<endl;

    // 将读取掉的报文删掉，packaging中可能还有后续的报文
    packaging.erase(0, targetlen);
    return payloadlen;
}

// Request && Response都要提供序列化和反序列化功能

// 请求
class Request
{
public:
    Request()
    {
    }

    Request(int x, int y, char op)
        : _x(x), _y(y), _op(op) {}

    // x + y
    // struct->string
    // 从各种类型序列化成字符串
    bool Serialize(string &out)
    {
#ifdef MYSELF
        out.clear();
        string stringx = to_string(_x);
        string stringy = to_string(_y);
        // 手动序列化
        out = stringx + SEP + _op + SEP + stringy;
        cout << "序列化后:" << out << endl;
        return true;
#else
        Json::Value root; // Value是一种万能对象，接收任意的kv类型
        root["x"] = _x;
        root["op"] = _op;
        root["y"] = _y;
        Json::FastWriter writer; // 用来序列化的
        // Json::StyledWriter writer;
        out = writer.write(root);

        cout << "序列化后:" << out<< endl;
    cout<<"------------------------------------"<<endl;
        return true;
#endif
    }

    // string->struct
    // 从字符串转换成原来的格式
    bool Deserialization(const string &in)
    {
#ifdef MYSELF
        // inStr : 10 + 20 => [0]=>10, [1]=>+, [2]=>20
        vector<string> data;
        // 将算式分割出来
        Util::StringSplit(in, SEP, data);
        if (data.size() != 3)
        {
            for (auto e : data)
            {
                cout << e << endl;
            }
            return false;
        }

        _x = atoi(data[0].c_str());
        _op = data[1][0];
        _y = atoi(data[2].c_str());
        cout << "反序列化后:"
             << "_x:" << _x << ","
             << "_op:" << _op << ","
             << "_y:" << _y << endl;
        return true;
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);
        _x = root["x"].asInt();
        _y = root["y"].asInt();
        _op = root["op"].asInt();

        cout << "反序列化后:"
             << "_x:" << _x << ","
             << "_op:" << _op << ","
             << "_y:" << _y << endl;
    cout<<"------------------------------------"<<endl;
       
        return true;
#endif
    }

    int _x;   // 左操作数
    int _y;   // 右操作数
    char _op; // 运算符
};

// 响应
class Response
{
public:
    Response()
    {
    }

    Response(int result, int code)
        : _result(result), _code(code)
    {
    }

    // struct->string
    bool Serialize(string &out)
    {
#ifdef MYSELF
        out.clear();
        string stringres = to_string(_result);
        string stringcd = to_string(_code);
        out = stringres + SEP + stringcd;
        cout << "序列化后:" << out << endl;
        return true;
#else
        Json::Value root;
        root["result"] = _result;
        root["code"] = _code;
        Json::FastWriter writer;
        out = writer.write(root);

        cout << "序列化后:" << out<< endl;
    cout<<"------------------------------------"<<endl;

        return true;
#endif
    }

    // string->struct
    bool Deserialization(const string &in)
    {
#ifdef MYSELF
        vector<string> data;
        Util::StringSplit(in, SEP, data);
        if (data.size() != 2)
        {
            return false;
        }
        _result = atoi(data[0].c_str());
        _code = atoi(data[1].c_str());
        cout << "反序列化后："
             << "_result:" << _result << " "
             << "_code:" << _code << endl;
        return true;
#else
        Json::Value root;
        Json::Reader reader;
        reader.parse(in, root);
        _result = root["result"].asInt();
        _code = root["code"].asInt();

        cout << "反序列化后："
             << "_result:" << _result << " "
             << "_code:" << _code << endl;
    cout<<"------------------------------------"<<endl;
    
        return true;

#endif
    }

    int _result;//计算出的结果
    int _code;//错误码
};